package uk.co.q3c.deplan.server.util;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;

import uk.co.q3c.deplan.client.domain.util.NamedObject;

/**
 * A wrapper for a standard HashMap useful for containing objects which implement the {@link PersistedObject} interface. When a new object
 * is put into the map, it's name property is used to provide the key. A listener is added to the object so that a name change also updates
 * its key entry in the map.<br>
 * <br>
 * 
 * @author DSowerby 1 Sep 2008 20:07:43
 * 
 * @param <V>
 */
@Improve(reason = "lookup is crude, could be faster")
public class CaseInsensitiveHashMap<V extends NamedObject> implements Serializable {
	private static final long serialVersionUID = 1L;
	private ArrayList<V> list;
	private transient boolean beforeLoadd;

	class NameChangeListener implements PropertyChangeListener {

		@SuppressWarnings("unchecked")
		@Override
		public void propertyChange(PropertyChangeEvent evt) {
			V v = (V) evt.getSource();
			String oldName = evt.getOldValue().toString();
			remove(oldName);
			put(v);

		}

	}

	// , String keyLabel, String valueLabel
	public CaseInsensitiveHashMap() {
		super();
		init();
	}

	public void init() {
		if (!beforeLoadd) {
			list = new ArrayList<V>();
			beforeLoadd = true;
		}

	}

	public void put(V object) {

		list.add(object);
	}

	public V get(String name) {
		if (name == null) {
			return null;
		}

		// return map.get(name.toLowerCase());
		V found = null;
		for (V object : list) {
			if (object.getName().equalsIgnoreCase(name)) {
				found = object;
				break;
			}

		}
		return found;
	}

	public boolean containsKey(String name) {
		if (name == null) {
			return false;
		}
		return get(name) != null;
	}

	public boolean containsValue(V object) {
		return list.contains(object);
	}

	public Collection<V> values() {
		return list;
	}

	public int size() {

		return list.size();
	}

	public V remove(String name) {
		if (name == null) {
			return null;
		}

		// return map.remove(name.toLowerCase());
		V object = get(name);
		list.remove(object);
		return object;
	}

	public void clear() {
		list.clear();

	}

	@Override
	public String toString() {
		return list.toString();
	}

}
